package jfood.chef;

import jfood.chef.Stemmer.Stem;
import jfood.ontology.meal.Ingredient;
import jfood.ontology.meal.Meal;
import jfood.ontology.meal.Recipe;
import jfood.parser.AlphabetNormalizer;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;

public class DatabaseWriter {

	public DatabaseWriter(final String databasePath) {
		databasePath_ = databasePath;
	}


	public boolean databaseExists()
	{
		File file = new File(databasePath_);

		return file.exists();
	}
	
	public void writeMeals(final AbstractCollection<Meal> meals)
	{
		try {
			writeIngredients(meals);
			writeRecipes(meals);
			writeIngredientsStems(meals);
			writeMealStems(meals);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}	
	
	private void writeMealStems(Meal meal) throws IOException{
		BufferedWriter writer = new BufferedWriter(new FileWriter(databasePath_, true));
		
		String name = serializeMealName(meal);
		String mealName = serializeMealNameToStem(meal);
		
		writer.write("meal_stem(");
		writer.write(name);
		writer.write(",");
		writer.write(mealName);
		writer.write(").");
		writer.newLine();
		
		writer.close();
	}
	
	private void writeIngredients(Meal meal) throws IOException{
		BufferedWriter writer = new BufferedWriter(new FileWriter(databasePath_, true));
		
		String name = serializeMealName(meal);
		String ingredients = serializeIngredients(meal.getIngredients());
		writer.write("ingredients(");
		writer.write(name);
		writer.write(",");
		writer.write(ingredients);
		writer.write(").");
		writer.newLine();
		
		writer.close();
	}
	
	private void writeIngredientsStem(Meal meal) throws IOException{
		BufferedWriter writer = new BufferedWriter(new FileWriter(databasePath_, true));
		
		String name = serializeMealName(meal);
		String ingredients = serializeIngredientsStems(meal.getIngredients());
		writer.write("ingredients_stem(");
		writer.write(name);
		writer.write(",");
		writer.write(ingredients);
		writer.write(").");
		writer.newLine();
		
		writer.close();
	}

	
	private void writeRecipes(final AbstractCollection<Meal> meals) throws IOException
	{
		for (Meal meal: meals) {
			writeRecipe(meal);
		}
	}
	
	private void writeIngredients(final AbstractCollection<Meal> meals) throws IOException
	{
		for (Meal meal: meals) {
			writeIngredients(meal);
		}
	}
	
	private void writeIngredientsStems(final AbstractCollection<Meal> meals) throws IOException
	{
		for (Meal meal: meals) {
			writeIngredientsStem(meal);
		}
	}
	
	private void writeMealStems(final AbstractCollection<Meal> meals) throws IOException
	{
		for (Meal meal: meals) {
			writeMealStems(meal);
		}
	}

	
	private void writeRecipe(Meal meal) throws IOException{
		BufferedWriter writer = new BufferedWriter(new FileWriter(databasePath_, true));
		
		String nameStr = serializeMealName(meal);
		String recipeStr = serializeRecipe(meal.getRecipe());
		writer.write("recipe(");
		writer.write(nameStr);
		writer.write(",");
		writer.write(recipeStr);
		writer.write(").");
		writer.newLine();
	
		writer.close();
	}
	
	private String serializeRecipe(Recipe recipe) {
		String rec = AlphabetNormalizer.unAccent(recipe.getContent());
		
		return "['" + rec + "']";
	}
	
	private String serializeIngredients(ArrayList<Ingredient> ingredients) {
		StringBuilder builder = new StringBuilder();
		builder.append("[");
		Iterator<Ingredient> iterator =  ingredients.iterator();
		
		while(true){
			
			builder.append(serializeString(iterator.next().getName()));
			
			if(iterator.hasNext()){
				builder.append(",");
			}
			
			else{
				break;
			}
		}

		builder.append("]");
		return builder.toString().toLowerCase();
	}
	
	private String serializeIngredientsStems(ArrayList<Ingredient> ingredients) {
		StringBuilder builder = new StringBuilder();
		builder.append("[");
		Iterator<Ingredient> iterator =  ingredients.iterator();
		
		while(true){
			
			builder.append(serializeStringByStemmer(iterator.next().getName(),true));
			
			if(iterator.hasNext()){
				builder.append(",");
			}
			
			else{
				break;
			}
		}

		builder.append("]");
		return builder.toString().toLowerCase();
	}
	
	private String serializeMealName(final Meal meal) {
		return serializeString(meal.getName());
	}
	
	private String serializeMealNameToStem(final Meal meal) {
		return serializeStringByStemmer(meal.getName(),false);
	}
	
	private String serializeStringByStemmer(String string, boolean deleteNumbers) {
		StringBuilder builder = new StringBuilder();
		ArrayList<Stem> stems = stemmer_.stemSentenceWithForbiddens(string,deleteNumbers);
		
		builder.append("[");

		Stem first = stems.get(0);
		for (Stem s: stems)
		{
			if(s != first)
			{
				builder.append(",");
			}
			
			builder.append("['");
			String stemString = AlphabetNormalizer.unAccent(s.getStem());
			builder.append(stemString);
			builder.append("']");
		}
				
		builder.append("]");
		return builder.toString().toLowerCase();
	}
	
	private String serializeString(String string) {
		String tempString = AlphabetNormalizer.unAccent(string);
		StringTokenizer tokenizer = new StringTokenizer(tempString);
		StringBuilder builder = new StringBuilder();
		
		builder.append("[");

		while(true){
			builder.append("['");
			builder.append(tokenizer.nextToken());
			builder.append("']");

			boolean hasMoreTokens = tokenizer.hasMoreTokens();
			
			if(hasMoreTokens)
			{
				builder.append(",");
			}
			else
			{
				break;
			}
		}
		builder.append("]");
		return builder.toString().toLowerCase();
	}


	final static private Stemmer stemmer_ = new Stemmer();
	private String databasePath_;
}
